package com.navi.loaddata.loadService.impl.teg2Data;

import com.navi.loaddata.core.etlException.ETLException2;
import com.navi.loaddata.core.gpEntity.MArrayParamD;
import com.navi.loaddata.core.gpEntity.MParamD;
import com.navi.loaddata.core.gpEntity.WppTegStatistic2;
import com.navi.loaddata.core.mesEntity.MesCtPospairproduct;
import com.navi.loaddata.core.mesEntity.MesProducthistory;
import com.navi.loaddata.core.mysqlEntity.EtlConfDModel;
import com.navi.loaddata.core.oracleEntity.EtlCmnGlassV;
import com.navi.loaddata.core.oracleEntity.EtlProductV;
import com.navi.loaddata.core.oracleEntity.EtlStepV;
import com.navi.loaddata.core.oracleEntity.array.EtlArrayGlassV;
import com.navi.loaddata.core.oracleEntity.array.EtlArrayIvCurveV;
import com.navi.loaddata.core.oracleEntity.array.EtlArrayParamV;
import com.navi.loaddata.core.oracleEntity.base.EtlParamV;
import com.navi.loaddata.core.util.LoggerUtil;
import com.navi.loaddata.core.util.ProcessUtil;
import com.navi.loaddata.loadDao.SaveBaseDataDao;
import com.navi.loaddata.loadDao.SaveTeg2DataDao;
import com.navi.loaddata.loadService.impl.baseData.LoadMesBaseDataService;
import com.navi.loaddata.loadService.impl.baseData.ProcessBaseDataService;
import org.apache.commons.collections.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.navi.loaddata.core.constant.GenericDef.SHOP_ARY;

/**
 * @author jay
 */
@Service
public class LoadTeg2DataService {
    private static final Logger logger = LoggerFactory.getLogger(LoadTeg2DataService.class);
    private LoggerUtil loggerUtil = new LoggerUtil(this.getClass());

    @Autowired
    private LoadMesBaseDataService loadMesBaseDataService;
    @Autowired
    private ProcessBaseDataService processBaseDataService;
    @Autowired
    private ProcessTeg2DataService processTeg2DataService;
    @Autowired
    private LoadTeg2InfoService loadTegInfoService;
    @Autowired
    private SaveBaseDataDao saveBaseDataDao;
    @Autowired
    private SaveTeg2DataDao saveTeg2DataDao;


    public String[] loadTegDataMain(EtlConfDModel etlConfD) throws Exception {
        String[] resMsg = loadTegData(etlConfD);
        logger.info("LoadTegDataMain finish");
        return resMsg;
    }

    /**
     * Load Teg Data
     * <p>
     * load base -> session table
     * load defect data  -> session table
     * call base proc  -> auto commit
     * call defect proc -> no auto commit
     * delete defect session table
     *
     * @param etlConfD
     */
    private String[] loadTegData(EtlConfDModel etlConfD) throws Exception {
        String[] resMsg = new String[3];
        int okCnt = 0;
        int errCnt = 0;
        String errMsg = null;


        List<WppTegStatistic2> teg2EntityList = loadTegInfoService.loadTeg2Info(etlConfD);
        logger.info("Teg2 glass count {}", teg2EntityList.size());
        if (!teg2EntityList.isEmpty()) {
            // base
            List<EtlStepV> etlStepVList = loadMesBaseDataService.loadAllFinalStep(SHOP_ARY);
            List<EtlProductV> etlProductVList = loadMesBaseDataService.loadAllFinalProduct(SHOP_ARY);

            saveBaseDataDao.saveBaseData(etlConfD, etlStepVList, etlProductVList);

            //param
            List<MParamD> paramList = loadMesBaseDataService.loadParamInfo2(SHOP_ARY);
            List<EtlParamV> etlParamList = processBaseDataService.processParamInfo2(paramList);
            saveBaseDataDao.saveParamData(etlConfD, etlParamList);


            //cmn glass 可以批量入，  HST  资料也是
            Map<String, MesCtPospairproduct> mapMesCt1 = processBaseDataService.getMapMesCt1();
//            Map<String, MesCtPospairproduct> mapMesCt2 =processBaseDataService.getMapMesCt2();

            //common glass 单片保存
            List<EtlCmnGlassV> etlCmnGlassVList = new ArrayList<>();
            Map<String, String> cmnGlass = new HashedMap();
            teg2EntityList.forEach(glass -> cmnGlass.put(glass.getGlassId(), glass.getGlassId()));

            for (String glassId : cmnGlass.keySet()) {
                try {
                    List<MesProducthistory> commonGlassVList = loadMesBaseDataService.loadCommonGlassInfo(etlConfD, glassId);
                    EtlCmnGlassV etlCmnGlassV = processBaseDataService.processCmnGlass(etlConfD, commonGlassVList, mapMesCt1);
                    etlCmnGlassVList.add(etlCmnGlassV);
                } catch (ETLException2 e) {
                    logger.error("glassId=" + glassId + " " + e.getErrorCode().getErrorMsg() + "错误原因：\n" + LoggerUtil.stackTraceToString(e));
                    if (StringUtils.isEmpty(errMsg)) {
                        errMsg = "glassId=" + glassId + " " + e.getErrorCode().getErrorMsg() + "错误原因：" + e.getErrMsg();
                    } else {
                        errMsg += "glassId=" + glassId + " " + e.getErrorCode().getErrorMsg() + "错误原因：" + e.getErrMsg();
                    }
                    errCnt++;
                    continue;
                }
            }
            // save and procedure
            saveBaseDataDao.deleteTeg2CmnAndParam(etlConfD);
            saveBaseDataDao.saveCmnGlass(etlConfD, etlCmnGlassVList);
            logger.info("CMN_GLASS保存成功！");

            List<WppTegStatistic2> leftList = new ArrayList<>();
            Map<String, WppTegStatistic2> glassKey = new HashMap<>();//glassId,ope,proc_end,jge_cnt
            // Teg2
            for (WppTegStatistic2 teg2 : teg2EntityList) {
                //站点限制
                if (true == (ProcessUtil.opeLimit(teg2.getOpeId()))) {
                    logger.warn("glassId={} opeId={} 站点信息错误。忽略。", teg2.getGlassId(), teg2.getOpeId());
                    errCnt++;
                    continue;
                }

                if (glassKey.size() > 0 && null != glassKey.get(teg2.getGlassId() + "_" + teg2.getOpeId() + "_" + teg2.getProcEnd() + "_" + teg2.getJgeCnt())) {
                    logger.warn("{} 主键重复!", teg2.getGlassId() + "_" + teg2.getOpeId() + "_" + teg2.getProcEnd() + "_" + teg2.getJgeCnt());
                    errCnt++;
                    continue;
                }
                glassKey.put(teg2.getGlassId() + "_" + teg2.getOpeId() + "_" + teg2.getProcEnd() + "_" + teg2.getJgeCnt(), teg2);
                leftList.add(teg2);
            }

            for (WppTegStatistic2 teg2 : leftList) {
                try {
                    saveTeg2DataDao.deleteTeg2();
                    EtlArrayGlassV etlArrayGlassV = processTeg2DataService.processGlass(teg2);
                    saveTeg2DataDao.saveAryGlassData(etlArrayGlassV);
                    EtlArrayIvCurveV etlArrayIvCurveV = processTeg2DataService.processTeg2(teg2);
                    saveTeg2DataDao.saveTeg2Data(etlArrayIvCurveV);
                    okCnt++;
                } catch (ETLException2 e) {
                    errCnt++;
                    String err = "glassId=" + teg2.getGlassId() + " opeId=" + teg2.getOpeId() + " procEndTime=" + teg2.getProcEnd() +
                            " jgeCnt=" + teg2.getJgeCnt();
                    logger.error("{} 保存失败!失败原因：\n{}", err, LoggerUtil.stackTraceToString(e));
                    if (StringUtils.isEmpty(errMsg)) {
                        errMsg = err + " " + e.getErrorCode().getErrorMsg() + "\n失败原因：" + e.getErrMsg();
                    } else {
                        errMsg += err + " " + e.getErrorCode().getErrorMsg() + "\n失败原因：" + e.getErrMsg();
                    }
                }
            }
        } else {
            logger.info("没有此区间的数据。"); // todo print log & save etl data
        }
        return resMsg;
    }

}

